//============================================================================
// Copyright (C) 2012-2013 Brett R. Jones 
// All Rights Reserved
//
// You may redistribute and/or modify for non commercial and commercial uses 
// provided this copyright notice remains in place and is not modified
//
// This code is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// brettjones1900@gmail.com
// http://www.p2panarchy.com
//============================================================================

#include <string.h>
#include "SharedDirInfo.h"
#include "SharedFilesFinder.h"
#include <VxUtilLib/VxFileIsTypeFunctions.h>
#include <VxUtilLib/VxFileUtil.h>
#include <VxUtilLib/vx_debug.h>
#include <VxUtilLib/VxThread.h>
#include <VxUtilLib/VxSearchDefs.h>
#include <VxUtilLib/VxShortcut.h>


#ifndef WIN_PLATFORM
    //#include <sys/statvfs.h>
    //	#include <sys/types.h>
    //	#include <sys/stat.h>
    //	#include <unistd.h>
    //	#include <dirent.h>
    #define FILE_ATTRIBUTE_READONLY             0x00000001
    #define FILE_ATTRIBUTE_HIDDEN               0x00000002
    #define FILE_ATTRIBUTE_SYSTEM               0x00000004
    #define FILE_ATTRIBUTE_DIRECTORY            0x00000010
    #define FILE_ATTRIBUTE_ARCHIVE              0x00000020
    #define FILE_ATTRIBUTE_DEVICE               0x00000040
    #define FILE_ATTRIBUTE_NORMAL               0x00000080
    #define FILE_ATTRIBUTE_TEMPORARY            0x00000100
    #define FILE_ATTRIBUTE_SPARSE_FILE          0x00000200
    #define FILE_ATTRIBUTE_REPARSE_POINT        0x00000400
    #define FILE_ATTRIBUTE_COMPRESSED           0x00000800
    #define FILE_ATTRIBUTE_OFFLINE              0x00001000
    #define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED  0x00002000
    #define FILE_ATTRIBUTE_ENCRYPTED            0x00004000
    #define FILE_ATTRIBUTE_VIRTUAL              0x00010000
#else

#endif

//============================================================================
SharedDirInfo::SharedDirInfo(std::string& dir)
: m_strRootDir(dir)
, m_s64TotalByteCnt(0)
{
	VxMakeForwardSlashPath(m_strRootDir);
	if( m_strRootDir.length() )
	{
		if( '/' != m_strRootDir[m_strRootDir.length() - 1] )
		{
			m_strRootDir += "/";
		}
	}
	if( false == VxDirectoryExists( m_strRootDir.c_str() ) )
	{
		log_msg( LOG_ERROR, "SharedDirInfo::SharedDirInfo: ERROR not found directory %s\n", m_strRootDir.c_str() );
		m_strRootDir = "";
	}
}

//============================================================================
void SharedDirInfo::updateFileList( VxThread * poThread )
{
	if( false == VxDirectoryExists( m_strRootDir.c_str() ) )
	{
		log_msg( LOG_ERROR, "SharedDirInfo::SharedDirInfo: ERROR not found directory %s\n", m_strRootDir.c_str() );
		m_strRootDir = "";
		return;
	}

	std::vector<std::string> astrWildNameList;		// Extensions ( file extensions )
	astrWildNameList.push_back("*.*");

	SharedFileFinder oFileFinder;
	oFileFinder.FindFilesByName( 
		poThread,
		m_strRootDir,		// start path to search in
		astrWildNameList,	// Extensions of files to find
		m_oFileList,		// return FileInfo in array
		TRUE,				// recurse subdirectories if TRUE
		FALSE				// if TRUE dont return files matching filter else return files that do
		);
	if( poThread->isAborted() )
	{
		m_oFileList.clear();
	}
	else
	{
		if( false == massageFileList( poThread ) )
		{
			m_oFileList.clear();
		}
	}
}

//============================================================================
bool SharedDirInfo::massageFileList( VxThread * poThread )
{
	std::vector<SharedFileInfo>::iterator oIter;

	SharedFileInfo * poInfo;
	std::string strExt;
	for( oIter = m_oFileList.begin(); oIter != m_oFileList.end(); ++oIter )
	{
		if( poThread->isAborted() )
		{
			return false;
		}
		poInfo = &(*oIter);
		if( FILE_ATTRIBUTE_DIRECTORY & poInfo->m_u32Attributes )
		{
			poInfo->m_u8FileType = RC_FLAG_HAS_FOLDER;
			*poInfo = &poInfo->c_str()[m_strRootDir.length()];
		}
		else
		{
			//get file extension
			VxGetFileExtension( *poInfo, strExt );

#ifdef WIN_PLATFORM
			// resolve links
			if( 0 == strcmp( strExt.c_str(), "lnk" ) )
			{ 
				char as8FullPath[ MAX_PATH ];
				as8FullPath[ 0 ] = 0;
				HRESULT hr = VxResolveShortcut(	0,					// handle to window of caller
					poInfo->c_str(),	// .lnk file
					as8FullPath );		// return path to target file
				if( FAILED( hr ) )
				{
					log_msg( LOG_ERROR, "SharedFilesMgr::UpdateList: Unable to resove path in %s\n", poInfo->c_str() );
				}
				else
				{
					VxMakeForwardSlashPath(as8FullPath);
					*poInfo = as8FullPath;
					poInfo->m_s64FileLen = VxGetFileLen( as8FullPath );
					VxGetFileExtension( *poInfo, strExt );
				}
			}
#endif // WIN_PLATFORM
			if( poThread->isAborted() )
			{
				return false;
			}
			const char * pExt = strExt.c_str();
			if( IsImageFileExtention( pExt ) )
			{
				poInfo->m_u8FileType = RC_FLAG_HAS_IMAGE_FILES;
				setHasImageFiles( true );
			}
			else if( IsAudioFileExtention( pExt ) )
			{
				poInfo->m_u8FileType = RC_FLAG_HAS_AUDIO_FILES;
				setHasAudioFiles( true );
			}
			else if( IsVideoFileExtention( pExt ) )
			{
				poInfo->m_u8FileType = RC_FLAG_HAS_VIDEO_FILES;
				setHasVideoFiles( true );
			}
			//else if( IsExecutableFileExtention( pExt ) )
			//{
			//	poInfo->m_u8FileType = FILE_TYPE_EXECUTABLE;
			//	m_u8FileTypes |= FILE_TYPE_EXECUTABLE;
			//}
			//else if( IsArchiveOrDocFileExtention( pExt ) )
			//{
			//	poInfo->m_u8FileType = FILE_TYPE_ARCHIVE_OR_DOC;
			//	m_u8FileTypes |= FILE_TYPE_ARCHIVE_OR_DOC;
			//}
			else if( IsCdImageFileExtention( pExt ) )
			{
				poInfo->m_u8FileType = RC_FLAG_HAS_CDIMAGE_FILES;
				setHasOtherFiles( true );
			}
			else
			{
				poInfo->m_u8FileType = RC_FLAG_HAS_OTHER_FILES;
				setHasOtherFiles( true );
			}
			m_s64TotalByteCnt += poInfo->m_s64FileLen;
			*poInfo = &poInfo->c_str()[m_strRootDir.length()];
		}
	}
	return true;
}

//============================================================================
bool SharedDirInfo::localFileNameToRemoteFileName( std::string& strLocalFileName, std::string& strRetRemoteFileName )
{
	if( m_strRootDir.length() )
	{
		if( 0 == strncmp( m_strRootDir.c_str(), strLocalFileName.c_str(), m_strRootDir.length() ) )
		{
			std::string strTruncatedFileName;
			strTruncatedFileName = &(strLocalFileName.c_str()[m_strRootDir.length()]);
			
			std::vector<SharedFileInfo>::iterator oIter;

			for( oIter = m_oFileList.begin(); oIter != m_oFileList.end(); ++oIter )
			{
				if( strTruncatedFileName == *oIter )
				{
					strRetRemoteFileName = strTruncatedFileName;
					return true;
				}
			}
		}
	}
	return false;
}

//============================================================================
bool SharedDirInfo::remoteFileNameToLocalFileName( std::string& strRemoteFileName, std::string& strRetLocalFileName )
{
	if( m_strRootDir.length() )
	{
		std::vector<SharedFileInfo>::iterator oIter;

		for( oIter = m_oFileList.begin(); oIter != m_oFileList.end(); ++oIter )
		{
			if( strRemoteFileName == *oIter )
			{
				strRetLocalFileName = m_strRootDir + strRemoteFileName;
				return true;
			}
		}
	}
	return false;
}

